
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>

#include "./protocol.h"

// 发送消息的函数，将数据发送到指定的消息队列
int msg_send(void *data, int msgid, int msg_len){
    if (msgsnd(msgid, data, msg_len, 0) < 0){
        perror("msgsnd()");
        exit(1);
    }
    return 0;
}

// 解析路径信息的函数
int parser(msg_path_t path, int msgid){
    int fd;
    msg_data_t will_send;
    msg_empty_t empty;

    // 打开要发送的文件路径
    fd = open(path.path, O_RDONLY);
    if(fd < 0){
        perror("open()");
        // 如果打开文件失败，发送错误信息
        will_send.mtype = MSG_DATA;
        strcpy(will_send.data, "error path!");
        will_send.data_len = strlen(will_send.data);

        msg_send(&will_send, msgid, sizeof(will_send) - sizeof(long));

        empty.mtype = MSG_EMPTY;
        msg_send(&empty, msgid, 0);

        exit(1);
    }

    // 返回文件内容
    int pass = 0;
    struct stat stat_fd;
    int len;

    // 获取文件的状态信息
    fstat(fd, &stat_fd);

    pass = 0;
    while(pass < stat_fd.st_size){
        // 读取文件内容并发送到消息队列
        len = read(fd, will_send.data, DATASIZE);
        will_send.data_len = len;
        pass += len;

        printf("file_size = %d, len = %d, pass = %d\n", stat_fd.st_size, len, pass);

        will_send.mtype = MSG_DATA;
        msg_send(&will_send, msgid, sizeof(will_send) - sizeof(long));
    }

    // 发送空消息表示文件传输完成
    empty.mtype = MSG_EMPTY;
    msg_send(&empty, msgid, 0);

    return 0;
}

int main(){
    key_t key;
    int msgid;
    msg_path_t recv_path;

    // 通过ftok函数生成一个唯一的消息队列标识符
    key = ftok(PATHNAME, PROJID);
    if(key < 0){
        perror("ftok()");
        exit(1);
    }

    // 创建一个新的消息队列或获取现有的消息队列标识符
    msgid = msgget(key, IPC_CREAT | 0644);
    if(msgid < 0){
        perror("msgget()");
        exit(1);
    }

    // 从消息队列接收路径信息
    if(msgrcv(msgid, &recv_path, sizeof(recv_path) - sizeof(long), 0, 0) < 0){
        perror("msgsnd()");
        exit(1);
    }
    puts("read path");

    // 解析接收到的路径信息，并将文件内容发送回发送者
    parser(recv_path, msgid);

    // 等待程序终止
    pause();

    // 删除消息队列
    msgctl(msgid, IPC_RMID, NULL);

    exit(0);
}
